﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;
using System.Reflection;
using AliCMS.SystemModule;

namespace AliCMS.TemplateEngine
{
    internal class Path : Tag
    {
        internal Path(Engine engine, int index, int length, int contentIndex, int contentLength, Tag parent)
            : base(engine, index, length, contentIndex, contentLength, parent)
        {
        }

        internal override void Init()
        {
            #region 获取Row,Col和Record
            foreach (Tag tag in ChildTags)
            {
                if (tag is Row)
                {
                    _row = tag;
                    break;
                }

                if (tag is Col)
                {
                    _col = tag;
                    break;
                }

                if (tag is Record)
                {
                    _record = tag;
                    break;
                }
            }

            if (_row == null && _col == null && _record == null)
            {
                Exception exp = new Exception("lang_parse_template_path_child_not_correct");
                Engine.ReportError(exp, Index);
            }

            if (_row != null && _col == null)
            {
                if (_row.ChildTags.Count != 1)
                {
                    Exception exp = new Exception("lang_parse_template_row_just_include_one_tag");
                    Engine.ReportError(exp, _row.Index);
                }

                if (_row.ChildTags[0] is Col)
                {
                    _col = _row.ChildTags[0];
                }
                else if (_row.ChildTags[0] is Record)
                {
                    _record = _row.ChildTags[0];
                }
                else
                {
                    Exception exp = new Exception("lang_parse_template_row_just_include_col_record");
                    Engine.ReportError(exp, _row.Index);
                }
            }

            if (_record == null)
            {
                if (_col.ChildTags.Count != 1)
                {
                    Exception exp = new Exception("lang_parse_template_col_just_include_one_tag");
                    Engine.ReportError(exp, _col.Index);
                }

                if (_col.ChildTags[0] is Record)
                {
                    _record = _col.ChildTags[0];
                }
                else
                {
                    Exception exp = new Exception("lang_parse_template_col_just_include_record");
                    Engine.ReportError(exp, _col.Index);
                }
            }
            #endregion

            Regex re = null;
            Match match = null;

            #region Mark
            _mark = String.Empty;
            re = new Regex("Mark=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
                _mark = match.Groups["v"].Value;
            #endregion

            #region Module
            _module = Engine.GetModuleByMark(_mark);
            #endregion

            #region Object
            if (_module != null)
            {
                re = new Regex("Object=\"(?<v>.*?)\"", RegexOptions.Compiled);
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
                if (match.Success)
                {
                    string objectName = match.Groups["v"].Value;

                    DataRow[] rows = Manager.Objects.Select(Alias.Module.Object.Namespace + "='" + _module[Alias.Module.Namespace] + "' and FullName='" + objectName + "'");
                    if (rows.Length == 0)
                    {
                        Exception exp = new Exception("lang_parse_template_module_not_include_object");
                        exp.Data.Add(3, _module[Alias.Module.Name]);
                        exp.Data.Add(4, objectName);
                        Engine.ReportError(exp, Index);
                    }

                    _object = rows[0];

                    #region InterfaceName
                    _interfaceName = String.Empty;
                    int dot = objectName.LastIndexOf('.');
                    if (dot != -1)
                        _interfaceName = objectName.Insert(dot + 1, "I");
                    else
                        _interfaceName = "I" + objectName;
                    #endregion
                }
            }
            #endregion           

            #region IncludeCurrentChannel
            _includeCurrentChannel = "false";
            re = new Regex("IncludeCurrentChannel=\"(?<v>.*?)\"", RegexOptions.Compiled);
            match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
                _includeCurrentChannel = match.Groups["v"].Value.ToLower();
            #endregion

            #region id
            _id = Id;
            if (String.IsNullOrEmpty(_id))
                _id = UniqueName + "ID";
            #endregion

            #region PathInTemplate
            _pathInTemplate = String.Empty;
            re = new Regex("Template=\"(?<v>.*?)\"", RegexOptions.Compiled);
            match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
                _pathInTemplate = match.Groups["v"].Value;
            #endregion

            #region 需要处理的子标签输出表达式
            if (_record != null)
            {
                _aliasStatment = new StringBuilder();
                _statment = new StringBuilder();
                _complex = new StringBuilder();
                _repeatCheckList = new List<string>();
                InitAliasStatment(_record.ChildTags);
            }
            #endregion
        }
        internal override void Parse()
        {
            ParseToCode();
            ParseToXml();
        }
        internal override string ParseVariable(Expression variable)
        {
            Match match = Regex.Match(variable.Value, @"((?<id>[a-zA-Z_]\w*)\[(?<counter>\d+)\]\[(?<name>[a-zA-Z_]\w*)\])|((?<id>[a-zA-Z_]\w*)\[(?<name>[a-zA-Z_]\w*)\])|(\[(?<name>[a-zA-Z_]\w*)\])|(?<name>[a-zA-Z_]\w*)");
            if (!match.Success)
                return null;

            if (match.Groups["id"].Success && match.Groups["id"].Value != Id)
                return null;

            string counter = String.Empty;
            if (match.Groups["counter"].Success)
                counter = match.Groups["counter"].Value;
            else
                counter = _id + "Counter";

            if (match.Groups["name"].Value == "Name")
                return _id + ".Rows[" + counter + "][\"Name\"]";
            else if (match.Groups["name"].Value == "URL")
                return _id + ".Rows[" + counter + "][\"URL\"]";
            else
                return null;
        }

        private void InitAliasStatment(List<Tag> childTags)
        {
            foreach (Tag tag in childTags)
            {
                if (tag is List || tag is Tree)
                    continue;

                if (!(tag is OutputStatment))
                {
                    InitAliasStatment(tag.ChildTags);
                    continue;
                }

                OutputStatment osTag = tag as OutputStatment;

                string content = Engine.Text.Substring(osTag.ContentIndex, osTag.ContentLength);
                if (content == "Index")
                {
                    osTag.IsAliasStatment = true;
                    osTag.AliasXml = content;
                    osTag.AliasCode = "null";

                    if (_repeatCheckList.Contains(content))
                        continue;

                    _aliasStatment.Append("replacementPair[\"{#" + osTag.AliasXml + "#}\"] = " + osTag.AliasCode + ";");
                }
                else if (content == "URL" || content == "Name")
                {
                    osTag.IsAliasStatment = true;
                    osTag.AliasXml = content;
                    osTag.AliasCode = "\"" + content + "\"";

                    if (_repeatCheckList.Contains(content))
                        continue;

                    _aliasStatment.Append("replacementPair[\"{#" + osTag.AliasXml + "#}\"] = " + osTag.AliasCode + ";");
                }

                if (osTag.IsAliasStatment)
                    _repeatCheckList.Add(content);
            }
        }
        private void ParseToCode()
        {
            StringBuilder result = new StringBuilder();
            Regex re = null;
            Match match = null;

            #region InstanceID
            string instanceID = "int instanceID;\r\n";
            if (String.IsNullOrEmpty(_mark))
            {
				if (Engine.IsMultiSite)
					instanceID += "instanceID = SubInstanceID;";
				else
					instanceID += "instanceID = InstanceID;";
			}
            else
            {
                //if ((bool)_module[Alias.Module.IsSystem])
                //    instanceID += "instanceID = SystemInstanceID;";
                //else if ((bool)_module[Alias.Module.IsMember] && String.IsNullOrEmpty(_mark))
                //    instanceID += "instanceID = (int)Manager.Channels.Select(AliCMS.SystemModule.Alias.Channel.ID + \" IS NOT NULL AND \" + AliCMS.SystemModule.Alias.Channel.InnerID + \"=\" + Channel[AliCMS.SystemModule.Alias.Channel.InnerID])[0][AliCMS.SystemModule.Alias.Instance.InnerID];";
                //else
                    instanceID += "instanceID = (int)" + Engine.ParseChannel(_mark) + "[AliCMS.SystemModule.Alias.Instance.InnerID];";
            }
            #endregion

            #region RowSeparator
            StringBuilder rowSeparatorReplacement = new StringBuilder();
            if (_row != null)
            {
                foreach (Tag tag in _row.ChildTags)
                {
                    if (tag is Separator)
                    {
                        foreach (Tag separatorChildTag in tag.ChildTags)
                        {
                            if (separatorChildTag is Code)
                            {
                                rowSeparatorReplacement.Append(separatorChildTag.ResultCode);
                            }
                            else if (tag is OutputStatment)
                            {
                                result.Append("object " + tag.UniqueName + " = " + tag.ResultCode + ";\r\n");
                                result.Append(UniqueName + " = " + UniqueName + ".Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + " == null ? \"\" : " + tag.UniqueName + ".ToString());\r\n");
                            }
                            else if (separatorChildTag is IfStatment)
                            {
                                rowSeparatorReplacement.Append(separatorChildTag.ResultCode);
                                rowSeparatorReplacement.Append("rowSeparator = rowSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                            else if (separatorChildTag.ResultCode != null && Regex.IsMatch(separatorChildTag.ResultCode, "protected string " + separatorChildTag.UniqueName + @"\s+{\s+get\s+"))
                            {
                                rowSeparatorReplacement.Append("rowSeparator = rowSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                        }
                    }
                }
            }
            #endregion

            #region ColSeparator
            StringBuilder colSeparatorReplacement = new StringBuilder();
            if (_col != null)
            {
                foreach (Tag tag in _row.ChildTags)
                {
                    if (tag is Separator)
                    {
                        foreach (Tag separatorChildTag in tag.ChildTags)
                        {
                            if (separatorChildTag is Code)
                            {
                                colSeparatorReplacement.Append(separatorChildTag.ResultCode);
                            }
                            else if (tag is OutputStatment)
                            {
                                result.Append("object " + tag.UniqueName + " = " + tag.ResultCode + ";\r\n");
                                result.Append(UniqueName + " = " + UniqueName + ".Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + " == null ? \"\" : " + tag.UniqueName + ".ToString());\r\n");
                            }
                            else if (separatorChildTag is IfStatment)
                            {
                                colSeparatorReplacement.Append(separatorChildTag.ResultCode);
                                colSeparatorReplacement.Append("colSeparator = colSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                            else if (separatorChildTag.ResultCode != null && Regex.IsMatch(separatorChildTag.ResultCode, "protected string " + separatorChildTag.UniqueName + @"\s+{\s+get\s+"))
                            {
                                colSeparatorReplacement.Append("colSeparator = colSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                        }
                    }
                }
            }
            #endregion

            #region RecordReplacement
            StringBuilder recordReplacement = new StringBuilder();
            if (_record != null)
            {
                MakeRecordReplacementCode(_record);

                recordReplacement.Append(_complex);
                recordReplacement.Append(_statment);
                recordReplacement.Append(_aliasStatment);
            }
            #endregion

            #region AllReplacement
            StringBuilder allReplacement = new StringBuilder();
            foreach (Tag tag in ChildTags)
            {
                if (tag is Row || tag is Col || tag is Record)
                    continue;

                if (tag is Code)
                {
                    allReplacement.Append(tag.ResultCode);
                }
                else if (tag is OutputStatment)
                {
                    allReplacement.Append("object " + tag.UniqueName + " = " + tag.ResultCode + ";\r\n");
                    allReplacement.Append("all.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + " == null ? \"\" : " + tag.UniqueName + ".ToString());\r\n");
                }
                else if (tag is IfStatment)
                {
                    allReplacement.Append(tag.ResultCode);
                    allReplacement.Append("all.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                }
                else if (tag.ResultCode != null && Regex.IsMatch(tag.ResultCode, "protected string " + tag.UniqueName + @"\s+{\s+get\s+"))
                {
                    allReplacement.Append("all.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                }
            }
            #endregion

            #region CurrentChannel
            string currentDebug = String.Empty;
            if (Engine.Debug)
                currentDebug = @"newRow[""URL""] = newRow[""URL""].ToString().Insert(Manager.GetWebPath().Length, ""debug/"");";
            string currentChannel = @"
                                newRow = <%ID%>_.NewRow();
								newRow[""Name""] = <%ChannelName%>;
                                if (!isMultiSite && !String.IsNullOrEmpty(Channel[AliCMS.SystemModule.Alias.Channel.Domain].ToString()))
                                {
                                    newRow[""URL""] = ""/""<%Debug%>;
                                }
                                else
                                {
                                    string path = <%SubWebPath%> + <%Channel%>[<%ChannelNamespace%>.Alias.Channel.Path];

                                    #region 包含正则表达式情况
                                    if (path.IndexOf('{') != -1)
                                    {
                                        System.Text.RegularExpressions.Match match = System.Text.RegularExpressions.Regex.Match(path, @""\{(?<name>\w+)(:.*?)?(?<!\\)\}"");
                                        if (match.Success && !String.IsNullOrEmpty(Request.QueryString[match.Groups[""name""].Value]))
                                        {
                                            path = path.Remove(match.Index, match.Length).Insert(match.Index, Request.QueryString[match.Groups[""name""].Value]);
                                        }
                                    }
                                    #endregion
                                    newRow[""URL""] = path + Channel[AliCMS.SystemModule.Alias.Channel.DefaultDocument].ToString()  + Channel[AliCMS.SystemModule.Alias.Channel.Extension];
                                    " + currentDebug + @"
                                }

								//注：不再考虑Fake404。彻底没有问题时，才移除下面注释的代码
                                //if (Convert.ToBoolean(Manager.Site[AliCMS.SystemModule.Alias.InstanceConfig.Fake404]) || Request.RawUrl.IndexOf(""/alicms.aspx?/"") != -1)
                                //    newRow[""URL""] = Manager.GetWebPath() + ""alicms.aspx?"" + newRow[""URL""];

                                <%ID%>_.Rows.Add(newRow);

                    ";
            #endregion

            #region Categories和Condition
            string categories = String.Empty;
            string condition = String.Empty;
            if (_object != null)
            {
                re = new Regex("(Guid=\"(?<g>.*?)\")|(InnerID=\"(?<i>.*?)\")", RegexOptions.Compiled);
                match = re.Match(Engine.Text, Index, Length);
                if (match.Success)
                {
                    _includeCurrentChannel = "true";

                    #region Condition
                    string guid = match.Groups["g"].Value;
                    string innerID = match.Groups["i"].Value;
                    if (!String.IsNullOrEmpty(innerID))
                        condition = "condition = <%Namespace%>.Alias.<%Object%>.InnerID + \"={\" + " + Engine.ParseExpression(this, innerID) + " + \"}\";\r\n";
                    else
                        condition = "condition = <%Namespace%>.Alias.<%Object%>.ID + \"={\" + " + Engine.ParseExpression(this, guid) + " + \"}\";\r\n";
                    #endregion

                    #region PathInTempalte
                    if (String.IsNullOrEmpty(_pathInTemplate))
                    {
                        string objectName = _object["FullName"].ToString();
                        for (int i = 0; i < objectName.Length; i++)
                        {
                            if (objectName[i] == '.')
                            {
                                _pathInTemplate += "/";
                            }
                            else
                            {
                                if (i > 0 && Char.IsUpper(objectName[i]))
                                    _pathInTemplate += "_";
                                _pathInTemplate += Char.ToLower(objectName[i]);
                            }
                        }
                    }
                    #endregion

                    categories = @"
                            <%InstanceID%>
                            using (<%Namespace%>.<%Interface%> bll = (<%Namespace%>.<%Interface%>)Manager.CreateObject(""<%Object%>"", instanceID, PageLang, false))
                            {
                                string condition = null;
                                <%Condition%>

                                DataTable table = bll.List(1, 1, condition, null);
                                if (table.Rows.Count == 0)
                                    return <%ID%>_;

                                int pos = <%ID%>_.Rows.Count;

                                newRow = <%ID%>_.NewRow();
                                newRow[""Name""] = table.Rows[0][<%Namespace%>.Alias.<%Object%>.Name].ToString();
                                newRow[""URL""] = BuildUrl(Channel, ""<%PathInTemplate%>"", ""ID="" + table.Rows[0][<%Namespace%>.Alias.<%Object%>.InnerID]);
                                <%ID%>_.Rows.InsertAt(newRow, pos);

                                while (!Guid.Equals(table.Rows[0][<%Namespace%>.Alias.<%Object%>.ParentID], Guid.Empty))
                                {
                                    table = bll.List(1, 1, <%Namespace%>.Alias.<%Object%>.ID + ""="" + table.Rows[0][<%Namespace%>.Alias.<%Object%>.ParentID], null);

                                    newRow = <%ID%>_.NewRow();
                                    newRow[""Name""] = table.Rows[0][<%Namespace%>.Alias.<%Object%>.Name].ToString();
                                    newRow[""URL""] = BuildUrl(Channel, ""<%PathInTemplate%>"", ""ID="" + table.Rows[0][<%Namespace%>.Alias.<%Object%>.InnerID]);
                                    <%ID%>_.Rows.InsertAt(newRow, pos);
                                }
                            }
                            ";
                }
            }
            #endregion

            result.Append(@"
                            private int <%ID%>Counter = 0;
                            private object <%ID%>Record = null;
                            private DataTable <%ID%>_;
                            private DataTable <%ID%>
                            {
                                get
                                {
                                    if (<%ID%>_ != null)
                                        return <%ID%>_;

                                    <%ID%>_ = new DataTable();
                                    <%ID%>_.Columns.Add(""Name"", typeof(string));
                                    <%ID%>_.Columns.Add(""URL"", typeof(string));

									bool isMultiSite = <%IsMultiSite%>;

                                    DataRow newRow = null;

                                    <%CurrentChannel%>

                                    Guid parentID = (Guid)<%Channel%>[<%ChannelNamespace%>.Alias.Channel.ParentID];
                                    while (parentID != Guid.Empty)
                                    {
                                        DataRow row = <%Channels%>.Select(<%ChannelNamespace%>.Alias.Channel.ID + ""='"" + parentID + ""'"")[0];

                                        newRow = <%ID%>_.NewRow();
										newRow[""Name""] = <%RowChannelName%>;
                                        string path = row[<%ChannelNamespace%>.Alias.Channel.Path].ToString();
                                        #region 包含正则表达式情况
                                        if (path.IndexOf('{') != -1)
                                        {
                                            System.Text.RegularExpressions.Match match = System.Text.RegularExpressions.Regex.Match(path, @""\{(?<name>\w+)(:.*?)?(?<!\\)\}"");
                                            if (match.Success && !String.IsNullOrEmpty(Request.QueryString[match.Groups[""name""].Value]))
                                            {
                                                path = path.Remove(match.Index, match.Length).Insert(match.Index, Request.QueryString[match.Groups[""name""].Value]);
                                            }
                                        }
                                        #endregion

										<%NewRowURL%>

										<%ID%>_.Rows.InsertAt(newRow, 0);
                                        parentID = (Guid)row[<%ChannelNamespace%>.Alias.Channel.ParentID];
                                    }

                                    <%Categories%>

                                    return <%ID%>_;
                                }
                            }
                            protected string <%Name%>
                            {
                                get
                                {
                                    XmlNode node = _xmlTemplate.SelectSingleNode(""//<%Name%>"");
                                    Dictionary<string, object> replacementPair = new Dictionary<string, object>();
                                    <%RecordReplacement%>
                                    StringBuilder all = Manager.Build(node, <%ID%>, replacementPair, ref <%ID%>Record, ref <%ID%>Counter);
                                    <%RowSeparatorReplacement%>
                                    <%ColSeparatorReplacement%>
                                    <%AllReplacement%>
                                    return all.ToString();
                                }
                            }
                          ");
            if (_includeCurrentChannel != "false")
                result.Replace("<%CurrentChannel%>", currentChannel);
            else
                result.Replace("<%CurrentChannel%>", String.Empty);
            if (_object != null)
            {
                result.Replace("<%Categories%>", categories);
                result.Replace("<%Condition%>", condition);
                result.Replace("<%PathInTemplate%>", _pathInTemplate);
                result.Replace("<%Namespace%>", _module[Alias.Module.Namespace].ToString());
                result.Replace("<%Interface%>", _interfaceName);
                result.Replace("<%Object%>", _object["FullName"].ToString());
                result.Replace("<%InstanceID%>", instanceID);
            }
            else
            {
                result.Replace("<%Categories%>", String.Empty);
            }
			if (Engine.IsMultiSite)
			{
				result.Replace("<%IsMultiSite%>", "true");
				result.Replace("<%SubWebPath%>", "SubWebPath");
				result.Replace("<%Channel%>", "SubChannel");
				result.Replace("<%Channels%>", "SubChannels");
				result.Replace("<%ChannelNamespace%>", "AliCMS.SiteModule");
				result.Replace("<%ChannelName%>", "SubChannel[AliCMS.SiteModule.Alias.Channel.Name]");
				result.Replace("<%RowChannelName%>", "row[AliCMS.SiteModule.Alias.Channel.Name]");
				result.Replace("<%NewRowURL%>", @"
													if (String.IsNullOrEmpty(SubSite[AliCMS.SiteModule.Alias.Site.Domain].ToString()))
														newRow[""URL""] = SubWebPath;
													else
														newRow[""URL""] = SubSite[AliCMS.SiteModule.Alias.Site.Domain];
													newRow[""URL""] += path + Channel[AliCMS.SystemModule.Alias.Channel.DefaultDocument].ToString()  + Channel[AliCMS.SystemModule.Alias.Channel.Extension];
												");
			}
			else
			{
				result.Replace("<%IsMultiSite%>", "false");
				result.Replace("<%SubWebPath%>", "\"\"");
				result.Replace("<%Channel%>", "Channel");
				result.Replace("<%Channels%>", "Manager.Channels");
				result.Replace("<%ChannelNamespace%>", "AliCMS.SystemModule");
				result.Replace("<%ChannelName%>", "Channel[AliCMS.SystemModule.Alias.Channel.Name + PageLang]");
				result.Replace("<%RowChannelName%>", "row[AliCMS.SystemModule.Alias.Channel.Name + PageLang]");
				result.Replace("<%NewRowURL%>", @"
													if (Convert.IsDBNull(row[AliCMS.SystemModule.Alias.Channel.TemplatePath]))
														newRow[""URL""] = path;
													else if (!String.IsNullOrEmpty(row[AliCMS.SystemModule.Alias.Channel.Domain].ToString()))
														newRow[""URL""] = row[AliCMS.SystemModule.Alias.Channel.Domain].ToString().Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries) + row[AliCMS.SystemModule.Alias.Channel.DefaultDocument].ToString() + row[AliCMS.SystemModule.Alias.Channel.Extension];
													else if (!String.IsNullOrEmpty(Channel[AliCMS.SystemModule.Alias.Channel.Domain].ToString()))
														newRow[""URL""] = Manager.Site[AliCMS.SystemModule.Alias.InstanceConfig.Domain]<%Debug%> + path.TrimStart('/') + row[AliCMS.SystemModule.Alias.Channel.DefaultDocument].ToString() + row[AliCMS.SystemModule.Alias.Channel.Extension];
													else
														newRow[""URL""] = Manager.GetWebPath()<%Debug%> + path.TrimStart('/') + row[AliCMS.SystemModule.Alias.Channel.DefaultDocument].ToString() + row[AliCMS.SystemModule.Alias.Channel.Extension];

													//注：不再考虑Fake404。彻底没有问题时，才移除下面注释的代码
													//if (newRow[""URL""].ToString().StartsWith(""/"") && (Convert.ToBoolean(Manager.Site[AliCMS.SystemModule.Alias.InstanceConfig.Fake404]) || Request.RawUrl.IndexOf(""/alicms.aspx?/"") != -1))
													//	newRow[""URL""] = Manager.GetWebPath() + ""alicms.aspx?"" + newRow[""URL""];
												");
			}
            result.Replace("<%ID%>", _id);
            result.Replace("<%Name%>", UniqueName);
            result.Replace("<%RowSeparatorReplacement%>", rowSeparatorReplacement.ToString());
            result.Replace("<%ColSeparatorReplacement%>", colSeparatorReplacement.ToString());
            result.Replace("<%RecordReplacement%>", recordReplacement.ToString());
            result.Replace("<%AllReplacement%>", allReplacement.ToString());
            if (Engine.Debug)
                result.Replace("<%Debug%>", " + \"debug/\"");
            else
                result.Replace("<%Debug%>", "");
            ResultCode = result.ToString();
        }
        private void ParseToXml()
        {
            #region Record和RecordSeparator
            _recordSeparatorXml = new StringBuilder();
            StringBuilder record = new StringBuilder();
            if (_record != null)
            {
                record.Append(Engine.Text.Substring(_record.ContentIndex, _record.ContentLength));
                MakeRecordReplacementXml(_record, record);
                record.Append("{#Record#}");
            }
            #endregion

            #region Col，ColSeparator，MaxRecord
            StringBuilder col = new StringBuilder();
            StringBuilder colSeparator = new StringBuilder();
            string maxRecord = "0";
            if (_col == null)
            {
                col.Append("{#Record#}");
            }
            else
            {
                Regex re = new Regex("MaxRecord=\"(?<v>.*?)\"", RegexOptions.Compiled);
                Match match = re.Match(Engine.Text, _col.Index, _col.ContentIndex - _col.Index);
                if (match.Success)
                    maxRecord = match.Groups["v"].Value;

                col.Append(Engine.Text.Substring(_col.ContentIndex, _col.ContentLength));
                for (int i = _col.ChildTags.Count - 1; i >= 0; i--)
                {
                    Tag tag = _col.ChildTags[i];
                    col.Remove(tag.Index - _col.ContentIndex, tag.Length);
                    if (tag is Separator)
                    {
                        colSeparator.Append(Engine.Text.Substring(tag.ContentIndex, tag.ContentLength));
                        for (int j = tag.ChildTags.Count - 1; j >= 0; j--)
                        {
                            Tag separatorChild = tag.ChildTags[j];
                            colSeparator.Remove(separatorChild.Index - tag.ContentIndex, separatorChild.Length);
                            if (separatorChild is IfStatment || (separatorChild.ResultCode != null && Regex.IsMatch(separatorChild.ResultCode, "protected string " + separatorChild.UniqueName + @"\s+{\s+get\s+")))
                                colSeparator.Insert(separatorChild.Index - tag.ContentIndex, "{#" + separatorChild.UniqueName + "#}");
                        }

                    }
                    else if (tag is Record)
                    {
                        col.Insert(tag.Index - _col.ContentIndex, "{#Record#}");
                    }
                }
            }
            col.Append("{#Col#}");
            #endregion

            #region Row，RowSeparator，MaxCol
            StringBuilder row = new StringBuilder();
            StringBuilder rowSeparator = new StringBuilder();
            string maxCol = "0";
            if (_row == null)
            {
                row.Append("{#Col#}");
            }
            else
            {
                Regex re = new Regex("MaxCol=\"(?<v>.*?)\"", RegexOptions.Compiled);
                Match match = re.Match(Engine.Text, _row.Index, _row.ContentIndex - _row.Index);
                if (match.Success)
                    maxCol = match.Groups["v"].Value;

                row.Append(Engine.Text.Substring(_row.ContentIndex, _row.ContentLength));
                for (int i = _row.ChildTags.Count - 1; i >= 0; i--)
                {
                    Tag tag = _row.ChildTags[i];
                    row.Remove(tag.Index - _row.ContentIndex, tag.Length);
                    if (tag is Separator)
                    {
                        rowSeparator.Append(Engine.Text.Substring(tag.ContentIndex, tag.ContentLength));
                        for (int j = tag.ChildTags.Count - 1; j >= 0; j--)
                        {
                            Tag separatorChild = tag.ChildTags[j];
                            rowSeparator.Remove(separatorChild.Index - tag.ContentIndex, separatorChild.Length);
                            if (separatorChild is IfStatment || (separatorChild.ResultCode != null && Regex.IsMatch(separatorChild.ResultCode, "protected string " + separatorChild.UniqueName + @"\s+{\s+get\s+")))
                                rowSeparator.Insert(separatorChild.Index - tag.ContentIndex, "{#" + separatorChild.UniqueName + "#}");
                        }

                    }
                    else if (tag is Col || tag is Record)
                    {
                        row.Insert(tag.Index - _row.ContentIndex, "{#Col#}");
                    }
                }
            }
            row.Append("{#Row#}");
            #endregion

            #region All
            StringBuilder all = new StringBuilder(Engine.Text.Substring(ContentIndex, ContentLength));
            for (int i = ChildTags.Count - 1; i >= 0; i--)
            {
                Tag tag = ChildTags[i];
                all.Remove(tag.Index - ContentIndex, tag.Length);
                if (tag is Row || tag is Col || tag is Record)
                    all.Insert(tag.Index - ContentIndex, "{#Row#}");
                else if (tag is IfStatment || tag is OutputStatment || (tag.ResultCode != null && Regex.IsMatch(tag.ResultCode, "protected string " + tag.UniqueName + @"\s+{\s+get\s+")))
                    all.Insert(tag.Index - ContentIndex, "{#" + tag.UniqueName + "#}");
            }
            #endregion

            #region 生成Xml
            StringBuilder result = new StringBuilder();
            result.Append(@"
		                <RowSeparator>
			                <![CDATA[
			                <%RowSeparator%>
			                ]]>
		                </RowSeparator>
		                <ColSeparator>
			                <![CDATA[
			                <%ColSeparator%>
			                ]]>
		                </ColSeparator>
		                <RecordSeparator>
			                <![CDATA[
			                <%RecordSeparator%>
			                ]]>
		                </RecordSeparator>
		                <Record>
			                <![CDATA[
			                <%Record%>
			                ]]>
		                </Record>
		                <Col MaxRecord=""<%MaxRecord%>"">
			                <![CDATA[
		                    <%Col%>
			                ]]>
		                </Col>
		                <Row MaxCol=""<%MaxCol%>"">
			                <![CDATA[
		                    <%Row%>
			                ]]>
		                </Row>
		                <All>
			                <![CDATA[
		                    <%All%>
			                ]]>
		                </All>
                        ");
            result.Replace("<%RowSeparator%>", rowSeparator.ToString());
            result.Replace("<%ColSeparator%>", colSeparator.ToString());
            result.Replace("<%RecordSeparator%>", _recordSeparatorXml.ToString());
            result.Replace("<%Record%>", record.ToString());
            result.Replace("<%Col%>", col.ToString());
            result.Replace("<%Row%>", row.ToString());
            result.Replace("<%MaxRecord%>", maxRecord);
            result.Replace("<%MaxCol%>", maxCol);
            result.Replace("<%All%>", all.ToString());
            ResultXml = result.ToString();
            #endregion
        }
        private void MakeRecordReplacementCode(Tag tag)
        {
            foreach (Tag childTag in tag.ChildTags)
            {
                if (childTag is Code || childTag.ResultCode == null) continue;

                if (childTag is OutputStatment)
                {
                    string content = Engine.Text.Substring(childTag.ContentIndex, childTag.ContentLength).Replace("\"", "\"\"");
                    if (_repeatCheckList.Contains(content))
                        continue;

                    _statment.Append(@"
                                        replacementPair[@""{#" + content + @"#}""] = new CustomBuild(
                                                                        delegate(DataRow record, int index)
                                                                        {
                                                                            object " + childTag.UniqueName + " = " + childTag.ResultCode + @";
                                                                            if (" + childTag.UniqueName + @" != null)
                                                                                return " + childTag.UniqueName + @".ToString();
                                                                            else
                                                                                return String.Empty;
                                                                        }
                                                                        );
                                                ");
                    _repeatCheckList.Add(content);
                }
                else if (childTag is IfStatment)
                {
                    _complex.Append(@"
                                        replacementPair[""{#" + childTag.UniqueName + @"#}""] = new CustomBuild(
                                                                        delegate(DataRow record, int index)
                                                                        {"
                                                                        + childTag.ResultCode +
                                                                    @"
                                                                            return " + childTag.UniqueName + @";
                                                                        }
                                                                        );
                                                ");
                }
                else if (childTag.ResultCode != null && Regex.IsMatch(childTag.ResultCode, "protected string " + childTag.UniqueName + @"\s+{\s+get\s+"))
                {
                    _complex.Append(@"
                                        replacementPair[""{#" + childTag.UniqueName + @"#}""] = new CustomBuild(
                                                                        delegate(DataRow record, int index)
                                                                        { return " + childTag.UniqueName + @";}
                                                                        );
                                                ");
                }
                else if (childTag is Separator)
                {
                    MakeRecordReplacementCode(childTag);
                }
            }
        }
        private void MakeRecordReplacementXml(Tag tag, StringBuilder result)
        {
            for (int i = tag.ChildTags.Count - 1; i >= 0; i--)
            {
                Tag childTag = tag.ChildTags[i];
                result.Remove(childTag.Index - tag.ContentIndex, childTag.Length);

                if (childTag is OutputStatment)
                {
                    string content = Engine.Text.Substring(childTag.ContentIndex, childTag.ContentLength);
                    result.Insert(childTag.Index - tag.ContentIndex, "{#" + content + "#}");
                }
                else if (childTag is IfStatment || (childTag.ResultCode != null && Regex.IsMatch(childTag.ResultCode, "protected string " + childTag.UniqueName + @"\s+{\s+get\s+")))
                {
                    result.Insert(childTag.Index - tag.ContentIndex, "{#" + childTag.UniqueName + "#}");
                }
                else if (childTag is Separator)
                {
                    _recordSeparatorXml.Append(Engine.Text.Substring(childTag.ContentIndex, childTag.ContentLength));
                    MakeRecordReplacementXml(childTag, _recordSeparatorXml);
                }
            }
        }

        #region Fields
        private Tag _record;
        private Tag _col;
        private Tag _row;
        private string _id;
        private string _interfaceName;
        private string _includeCurrentChannel;
        private string _mark;
        private string _pathInTemplate;
        private DataRow _module;
        private DataRow _object;
        private StringBuilder _recordSeparatorXml;
        private StringBuilder _aliasStatment;
        private StringBuilder _statment;
        private StringBuilder _complex;
        private List<string> _repeatCheckList;
        #endregion
    }
}
